package com.zmn.brs.business.impl.objective;

import com.github.ltsopensource.core.domain.Job;
import com.zmn.brs.business.interfaces.objective.ObjectiveTargetJobBService;
import com.zmn.brs.common.constant.TaskConst;
import com.zmn.brs.common.enums.MonitorCyclEnum;
import com.zmn.brs.common.enums.SceneTypeEnum;
import com.zmn.brs.cron.TaskScheduleModel;
import com.zmn.brs.model.entity.scene.Scene;
import com.zmn.brs.model.entity.scene.SceneQuery;
import com.zmn.brs.services.interfaces.scene.SceneService;
import com.zmn.brs.utils.CronUtil;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.manager.lts.interfaces.task.TaskManager;
import com.zmn.plat.common.dictionary.StatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;

/**
 * 描述：目标指标监控
 * @author chongw
 * @since 2021-06-10 17:49
 */
@Slf4j
@Service
public class ObjectiveTargetJobBServiceImpl implements ObjectiveTargetJobBService {

    private static final String TAG = "指标推送规则业务任务服务实现";

    @Resource
    private TaskManager taskManager;

    @Resource
    private SceneService sceneService;

    @Override
    public void initJob(SceneQuery query){
        query.setType(SceneTypeEnum.TARGET.getTypeId());
        //查询事件
        List<Scene> sceneList =  Optional.ofNullable(sceneService.listByQuery(query))
                .orElse(new ArrayList<>());
        sceneList.forEach(o -> {
            //判断状态是否停用,如果停用，则移除job
            if(StatusEnum.DISABLE.getCode().equals(o.getStatus())){
                this.cancelJob(o);
            }
            //启用则提交job任务
            else{
                this.submitJob(o);
            }
        });
    }

    @Override
    public void refreshJob(SceneQuery query){
        query.setType(SceneTypeEnum.TARGET.getTypeId());
        //查询事件
        List<Scene> sceneList =  Optional.ofNullable(sceneService.listByQuery(query))
                .orElse(new ArrayList<>());
        sceneList.forEach(o -> {
            List<String> jobTypes = Arrays.asList(o.getMonitorCycle().split(","));
            Arrays.stream(MonitorCyclEnum.values()).forEach( j ->{
                String jobType = String.valueOf(j.getTypeId());
                if(!jobTypes.contains(jobType)){
                    this.cancelTask(jobType, o.getSceneId());
                }else{
                    //提交计算任务
                    submitJob(o.getSceneId(), jobType, o.getComputeTime() ,TaskConst.TASK_ID_BRS_SCENE);
                    //提交推送任务
                    submitJob(o.getSceneId(), jobType, o.getPushTime() ,TaskConst.TASK_ID_BRS_SCENE_PUSH);
                }
            });
        });
    }

    @Override
    public void submitJob(Scene scene) {
        String monitorCycl = scene.getMonitorCycle();
        String computeTime = scene.getComputeTime();
        String pushTime = scene.getPushTime();
        String[] jobTypes = monitorCycl.split(",");
        Arrays.stream(jobTypes).forEach(jobTypeStr -> {
            //提交计算任务
            submitJob(scene.getSceneId(), jobTypeStr, computeTime ,TaskConst.TASK_ID_BRS_SCENE);
            //提交推送任务
            submitJob(scene.getSceneId(), jobTypeStr, pushTime ,TaskConst.TASK_ID_BRS_SCENE_PUSH);
        });
    }

    /**
     * 提交定时任务
     * @param sceneId
     * @param jobTypeStr
     * @param execTime
     * @param taskShard
     */
    protected void submitJob(Integer sceneId, String jobTypeStr, String execTime ,String taskShard){
        Integer jobType = Integer.parseInt(jobTypeStr);
        String[] time = execTime.split(":");
        String taskId = TaskConst.getBrsSceneTaskId(taskShard, sceneId , jobType);
        Job job = new Job();
        job.setTaskId(taskId);
        job.setParam(TaskManager.SHARD_FIELD, taskShard);
        job.setParam(TaskConst.SCENE_ID, String.valueOf(sceneId));
        job.setParam(TaskConst.JOB_TYPE, String.valueOf(jobType));
        Integer dayOfMonths = 1;
        //判断是否每月执行并且是否计算时间
        if(MonitorCyclEnum.MONTH.getTypeId().equals(jobType)
                && TaskConst.TASK_ID_BRS_SCENE.equals(taskShard)){
            time = TaskConst.MONTH_DEFAULT_TIME;
            dayOfMonths = -1;
        }
        job.setCronExpression(CronUtil.createCronExpression(
                TaskScheduleModel.builder()
                        .jobType(jobType)
                        .dayOfMonths(new Integer[]{dayOfMonths})
                        .dayOfWeeks(new Integer[]{2})
                        .hour(Integer.parseInt(time[0]))
                        .minute(Integer.parseInt(time[1]))
                        .second(Integer.parseInt(time[2]))
                        .build())
        );
        job.setReplaceOnExist(true);
        ResponseDTO<String> responseSubmit = taskManager.submitTask2(job);
        if(responseSubmit.isSuccess()){
            log.info("[{}],任务ID：{}, 场景ID：{}, 提交定时任务：{}", TAG, taskId, sceneId, responseSubmit);
        }
    }

    @Override
    public void cancelJob(Scene scene) {
        String[] jobTypes = scene.getMonitorCycle().split(",");
        Arrays.stream(jobTypes).forEach(jobType -> {
            this.cancelTask(jobType, scene.getSceneId());
        });
    }

    protected void cancelTask(String jobType , Integer sceneId){
        String computeTaskId = TaskConst.getBrsSceneTaskId(TaskConst.TASK_ID_BRS_SCENE, sceneId , jobType);
        ResponseDTO<String> responseComputeCancel = taskManager.cancelTask2(computeTaskId);
        log.info("[{}],任务ID：{}, 场景ID：{}, 取消计算定时任务：{}", TAG, computeTaskId, sceneId, responseComputeCancel);
        String pushTaskId = TaskConst.getBrsSceneTaskId(TaskConst.TASK_ID_BRS_SCENE_PUSH, sceneId , jobType);
        ResponseDTO<String> responsePushCancel = taskManager.cancelTask2(pushTaskId);
        log.info("[{}],任务ID：{}, 场景ID：{}, 取消推送定时任务：{}", TAG, pushTaskId, sceneId, responsePushCancel);
    }

}
